package com.stox.ui.javafx.charting.widget;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javafx.geometry.Side;
import javafx.scene.canvas.Canvas;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;

import com.stox.ui.javafx.charting.model.plot.AbstractPlot;
import com.stox.ui.javafx.charting.view.ChartingView;
import com.stox.ui.javafx.charting.widget.axis.AbstractVerticalAxis;
import com.stox.ui.javafx.charting.widget.axis.BlankVerticalAxis;
import com.stox.ui.javafx.charting.widget.axis.ValueAxis;

@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class Chart<T extends AbstractPlot> extends BorderPane {

	private final ChartingView chartingView;
	
	private final ResizableCanvas canvas = new ResizableCanvas(this);
	
	private final List<T> plots = new ArrayList<>();
	
	private AbstractVerticalAxis leftVerticalAxis = new ValueAxis();
	
	private AbstractVerticalAxis rightVerticalAxis = new BlankVerticalAxis();
	
	private T frontPlot;
	
	public Chart(ChartingView chartingView) {
		this.chartingView = chartingView;
		Pane pane = new Pane();
		pane.getChildren().add(canvas);
		setCenter(pane);
		
		leftVerticalAxis.setChart(this);
		leftVerticalAxis.setSide(Side.LEFT);
		rightVerticalAxis.setChart(this);
		rightVerticalAxis.setSide(Side.RIGHT);
		
		canvas.widthProperty().bind(pane.widthProperty());
		canvas.heightProperty().bind(pane.heightProperty());
	}
	
	public void update() {
		if(null == frontPlot) return;
		frontPlot.update();
		
		for(T abstractPlot : getPlots()) {
			abstractPlot.update();
		}
		
		if(null != leftVerticalAxis) leftVerticalAxis.update();
		if(null != rightVerticalAxis) rightVerticalAxis.update();
	}
	
	public void paint() {
		if(null == frontPlot) return;
		
		for(T abstractPlot : getPlots()) {
			abstractPlot.paint();
		}
		
		frontPlot.paint();
	}
	
	public Canvas getCanvas() {
		return canvas;
	}
	
	public List<T> getPlots() {
		return Collections.unmodifiableList(plots);
	}
	
	public void addPlot(int index, T plot) {
		plots.add(index, plot);
		plot.setChart(this);
	}
	
	public void addPlot(T plot) {
		plots.add(plot);
		plot.setChart(this);
	}

	public void removePlot(T plot) {
		plots.remove(plot);
		plot.setChart(null);
	}
	
	public ChartingView getChartingView() {
		return chartingView;
	}

	public T getFrontPlot() {
		return frontPlot;
	}

	public void setFrontPlot(T frontPlot) {
		this.frontPlot = frontPlot;
		frontPlot.setChart(this);
	}

	public AbstractVerticalAxis getLeftVerticalAxis() {
		return leftVerticalAxis;
	}

	public void setLeftVerticalAxis(AbstractVerticalAxis leftVerticalAxis) {
		this.leftVerticalAxis = leftVerticalAxis;
		setLeft(leftVerticalAxis);
		leftVerticalAxis.setHeight(getHeight());
	}

	public AbstractVerticalAxis getRightVerticalAxis() {
		return rightVerticalAxis;
	}

	public void setRightVerticalAxis(AbstractVerticalAxis rightVerticalAxis) {
		this.rightVerticalAxis = rightVerticalAxis;
		setRight(rightVerticalAxis);
		rightVerticalAxis.setHeight(getHeight());
	}
}
